package com.theme.passport.controller.app;

import cn.t.util.common.StringUtil;
import com.alibaba.fastjson.JSONObject;
import com.qiniu.util.Json;
import com.theme.common.base.DateHandler;
import com.theme.common.base.JSONHandler;
import com.theme.common.mvc.utils.RedisKeys;
import com.theme.common.mvc.view.R;
import com.theme.common.third.weather.*;
import com.theme.passport.controller.app.utils.JwtUtils;
import com.theme.passport.service.IWeatherApi;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.crypto.JwtSigner;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.tools.ant.types.selectors.modifiedselector.Algorithm;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.validation.Valid;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author: 可乐加糖
 * @create: 2022-06-28 16:30
 * @Description: 组件管理
 */
@Slf4j
@RestController
@RequestMapping("app/weather")
@Api("高德天气接口API")
public class WeatherController {

    @Value("${gaode.amapKey}")
    private String amapKey;

    @Resource(name = "redisTemplate")
    private ValueOperations<String, String> valueOperations;

    @GetMapping("realTime")
    @ApiOperation("获取实时的天气")
    public R realTime(@RequestParam(value = "adCode") String adCode) {
        Live live = WeatherHandler.getLive(adCode,amapKey);
        return R.ok().put("live", live);
    }

    @GetMapping("realTimeBak")
    @ApiOperation("获取实时的天气(后期备用,可以根据小时做缓存，60分钟后过期)")
    public R realTimeBak(@RequestParam(value = "adCode") String adCode) {
        String dateStr = DateHandler.getDateString(new Date()); //一小时为主2022-07-21 09:31:48
        String dateHour = dateStr.substring(0, 13).replace(" ", "").replace("-",""); //2022072109
        String cacheKey = adCode +"_" + dateHour;
        String cacheInfo = valueOperations.get(RedisKeys.concat(RedisKeys.AMAP_WEATHER, cacheKey));
        if (!StringUtil.isEmpty(cacheInfo)){
            Live live = JSONHandler.getGson().fromJson(cacheInfo, Live.class);
            return R.ok().put("live", live);
        }
        Live live = WeatherHandler.getLive(adCode,amapKey);
        if (live == null){
            return R.error("获取天气数据异常，请稍后重试！");
        }
        String val = JSONHandler.objectToJson(live);
        valueOperations.set(RedisKeys.concat(RedisKeys.AMAP_WEATHER, cacheKey),val,60, TimeUnit.MINUTES);
        return R.ok().put("live", live);
    }

    @GetMapping("futureTime")
    @ApiOperation("获取预告天气")
    public R futureTime(@RequestParam(value = "adCode") String adCode) {
        List<Weather> weather = WeatherHandler.getWeather(adCode, amapKey);
        return R.ok().put("futures", weather);
    }

    @GetMapping("getWeather")
    @ApiOperation("获取预告天气")
    public R getWeather(@RequestParam(value = "adCode") String cityCode,@RequestParam(value = "lat") String lat,@RequestParam(value = "lng") String lng) {

//        String cacheInfo = valueOperations.get(RedisKeys.concat(RedisKeys.AMAP_WEATHER, cityCode));
//        if (!StringUtil.isEmpty(cacheInfo)){
//            WeatherResult weather = JSONHandler.getGson().fromJson(cacheInfo, WeatherResult.class);
//            return R.ok().put("futures", weather);
//        }

//        WeatherResult weather = WeatherHandler.WeatherForThird(cityCode);
//        if (null == weather){
//            return  R.error("天气数据异常");
//        }
//        valueOperations.set(RedisKeys.concat(RedisKeys.AMAP_WEATHER, cityCode), JSONHandler.objectToJson(weather),10, TimeUnit.MINUTES);
//
          try {
            String token =  applyInterval();
            log.info("token:{}",token);

            WeatherResult weather = WeatherHandler.WeatherForApple(lat,lng,token);
//            valueOperations.set(RedisKeys.concat(RedisKeys.AMAP_WEATHER, cityCode), JSONHandler.objectToJson(weather),30, TimeUnit.MINUTES);
            return R.ok().put("futures", weather);
        } catch (Exception e) {
              log.info("获取预告天气 Exception  e:{}",e.toString());
              //出错了就去请求别的天气数据（这个数据有点问题但能显示）
              try {
                  WeatherResult weather = WeatherHandler.WeatherForThird(cityCode);
                  if (null == weather){
                      return  R.error("天气数据异常");
                  }
//                  valueOperations.set(RedisKeys.concat(RedisKeys.AMAP_WEATHER, cityCode), JSONHandler.objectToJson(weather),30, TimeUnit.MINUTES);
                  return R.ok().put("futures", weather);
              } catch (Exception ex) {
                  throw new RuntimeException(ex);
              }
          }


//



    }

//BGJQMTCZNDK0MZA2MTMXOQ==   BGJQMTCZNDK0MZA2MTMXOQ==

//    @Resource
//    private IWeatherApi weatherService;

//    @PostMapping("/index")
//    public R<Map<String, Object>> index(@RequestBody @Valid WeatherRequest request) {
//
//
//
//        return R.ok(weatherService.getWeatherByLocation(request));
//    }
//
    private String key = "MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgmnycLxGoYun8vfkXVhwUHyxXEAoDF/Rk6vG9LSebQ9qgCgYIKoZIzj0DAQehRANCAARneJndeRnwsbJXoaMw7m+Kl1e3+WPaj3As+DDvhpzWw9EMGWN+rU9dwAqmGMqJnBthky0QeNYtRtNyt3sdN7c6";

    String pemPrivateKey ="MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgevZzL1gdAFr88hb2" +
            "OF/2NxApJCzGCEDdfSp6VQO30hyhRANCAAQRWz+jn65BtOMvdyHKcvjBeBSDZH2r" +
            "1RTwjmYSi9R/zpBnuQ4EiMnCqfMPWiZqB4QdbAd0E7oH50VpuZ1P087G";

    private String testkey ="";

//      private String key =
//        "MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgmnycLxGoYun8vfkXVhwUHyxXEAoDF/Rk6vG9LSebQ9qgCgYIKoZIzj0DAQehRANCAARneJndeRnwsbJXoaMw7m+Kl1e3+WPaj3As+DDvhpzWw9EMGWN+rU9dwAqmGMqJnBthky0QeNYtRtNy" +
//        "t3sdN7c6";

    private String getWeatherToken() throws Exception {
        final String cacheKey = StringUtils.joinWith(":", "weather", "token");
//        Object cacheObject = RedisUtils.getCacheObject(cacheKey);
//        if (Objects.isNull(cacheObject)) {

            // Define JWT claims
            long currentTimeMillis = System.currentTimeMillis();
            Date now = new Date(currentTimeMillis);
            Date expiration = new Date(currentTimeMillis + 3600 * 1000L); // 1-hour expiration




//        final JWTSigner signer = JWTSignerUtil.hs256("123456".getBytes());

 //            JWTSigner signer = JWTSignerUtil.createSigner("ES256", privateKey);


            Map<String, Object> header = new HashMap<>();
            header.put("alg", "ES256"); // Algorithm used for signing
            header.put("kid", "W2PL78U5AP");  // Key ID



//            String token = Jwts.builder()
//                    .setHeaderParams(header)
//                    .setClaims(payload)
//                    .signWith( SignatureAlgorithm.ES256,privateKey) // Ensure correct method signature
//                    .compact();

            // 提前60s过期
//            RedisUtils.setCacheObject(cacheKey, token, Duration.ofSeconds(weatherProperties.getTokenTTL() - 60));

        byte[] keyBytes = Base64.getDecoder().decode(key);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("EC");  // Apple uses EC (Elliptic Curve) algorithm
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);

        Map<String, Object> payload = new HashMap<>();
        payload.put("iss", "BZXNDK2K96");    // Team ID
        payload.put("sub", "com.cykon.mytheme");  // Issuer ID
        payload.put("iat", 1735347076); // Issued at time in seconds
        payload.put("exp", 1735440952); // Expiration time in seconds

        Map<String,Object> jwtHeader = new HashMap<>();
        jwtHeader.put("alg","ES256");
        jwtHeader.put("kid","55WJZ5J252");
        jwtHeader.put("id","BZXNDK2K96.com.cykon.mytheme");
//        jwtHeader.put("typ","JWT");
         String accessToken = Jwts.builder()

                .setHeader(jwtHeader)
//                 .setHeaderParams(jwtHeader)
                 .setClaims(payload)
                .signWith(SignatureAlgorithm.ES256, privateKey)
                .compact();

            return accessToken;
//        }
//
//        return (String) cacheObject;
    }


    public static PrivateKey getPrivateKey(String filename, String algorithm) throws IOException {
        String content = new String(Files.readAllBytes(Paths.get(filename)), "utf-8");
        try {
            String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "")
                    .replace("-----END PRIVATE KEY-----", "")
                    .replaceAll("\\s+", "");

            KeyFactory kf = KeyFactory.getInstance(algorithm);
            return kf.generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("Java did not support the algorithm:" + algorithm, e);
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException("Invalid key format");
        }
    }


    protected String applyInterval() {
        //在此之前可以用redis做个缓存 我这里就不给大家写怎么做了

//        Map<String, Object> payload = new HashMap<>();
//        payload.put("iss", "BZXNDK2K96");    // Team ID
//        payload.put("sub", "com.cykon.mytheme");  // Issuer ID
//        payload.put("iat", 1735347076); // Issued at time in seconds
//        payload.put("exp", 1735440952); // Expiration time in seconds
//
//        Map<String,Object> jwtHeader = new HashMap<>();
//        jwtHeader.put("alg","ES256");
//        jwtHeader.put("kid","W2PL78U5AP");
//        jwtHeader.put("id","BZXNDK2K96.com.cykon.mytheme");


        PrivateKey privateKey = null;
        try {
            key = key.replace("-----BEGIN PRIVATE KEY-----", "")
                    .replace("-----END PRIVATE KEY-----", "")
                    .replaceAll("\\s+", "");

            byte[] keyBytes = Base64.getDecoder().decode(key);
//            byte[] keyBytes = Base64.getDecoder().decode(pemPrivateKey);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance("EC");  // Apple uses EC (Elliptic Curve) algorithm
            privateKey = keyFactory.generatePrivate(keySpec);
        } catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
            e.printStackTrace();  // 打印堆栈信息以便进一步分析
            throw new RuntimeException(e);
        }
        long currentTimeMillis = System.currentTimeMillis();

        Date now = new Date(currentTimeMillis);
        Date expiration = new Date(currentTimeMillis + 3600 * 1000L); // 1-hour expiration
        JSONObject head = new JSONObject();
        head.put("alg","ES256");
        head.put("kid", "55WJZ5J252");
        head.put("id", "BZXNDK2K96.com.cykon.mytheme");
        JSONObject payLoad = new JSONObject();
        payLoad.put("iss",  "BZXNDK2K96");
        payLoad.put("sub", "com.cykon.mytheme");
        //JWT签发时间
        payLoad.put("iat", currentTimeMillis/1000);
        //JWT过期时间
        payLoad.put("exp", currentTimeMillis/1000 + 3600 );
        log.info("expiration:{}",currentTimeMillis/1000 + 3600);
        log.info("now:{}",currentTimeMillis/1000);
//         payLoad.put("iat", 1735606447);

//         payLoad.put("exp", 1735635247);

        String accessToken = Jwts.builder()
                .setHeader(head)
                .setClaims(payLoad)
                .signWith(SignatureAlgorithm.ES256, privateKey)
                .compact();

//        requestTemplate.header("Authorization", "Bearer " + string);
        return accessToken;
    }

}
